<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <script>
        class HashMapNode {
            constructor(key, value) {
                this.key = key
                this.value = value
                this.next = null
            }
        }
        var MyHashMap = function() {
            this.hashMap = new Array(996).fill(null)
        };

        /** 
         * @param {number} key 
         * @param {number} value
         * @return {void}
         */
        MyHashMap.prototype.put = function(key, value) {
            // 如果在映射中找到对应的键值对，则更新
            const bucket = this.hashFunc(key)
            for (let i = this.hashMap[bucket]; i != null; i = i.next) {
                if (i.key === key) {
                    i.value = value
                    return
                }
            }
            // 若不存在，则新增节点
            const current = new HashMapNode(key, value)
            current.next = this.hashMap[bucket]
            this.hashMap[bucket] = current
            return
        };

        /** 
         * @param {number} key
         * @return {number}
         */
        MyHashMap.prototype.get = function(key) {
            const bucket = this.hashFunc(key)
                // 遍历链表，若存在对应key,则返回对应值，否则返回-1
            for (let i = this.hashMap[bucket]; i != null; i = i.next) {
                if (i.key === key) {
                    return i.value
                }
            }
            return -1
        };

        /** 
         * @param {number} key
         * @return {void}
         */
        MyHashMap.prototype.remove = function(key) {
            const bucket = this.hashFunc(key)
            let provide = null
                // 声明并定义前置节点为null
            for (let i = this.hashMap[bucket]; i != null; provide = i, i = i.next) {
                // 若发现存在对应key的键值对，则判断是否为链表头，再进行删除操作
                if (i.key === key) {
                    if (!provide) {
                        // 若为链表头，则将当前链表元素下一个赋值给原链表
                        this.hashMap[bucket] = i.next
                        return
                    }
                    // 若不为链表头，则将当前链表元素上一个节点provide的next赋值为当前链表元素i的next节点
                    provide.next = i.next
                    return
                }
            }
            // 若未找到对应元素，则返回空
            return
        };
        MyHashMap.prototype.hashFunc = function(key) {
            return key % 997
        };
        /**
         * Your MyHashMap object will be instantiated and called as such:
         * var obj = new MyHashMap()
         * obj.put(key,value)
         * var param_2 = obj.get(key)
         * obj.remove(key)
         */
        var a = new MyHashMap()
        a.put(1, 1)
        a.put(2, 2)
        a.get(1); // 返回 1 ，myHashMap 现在为 [[1,1], [2,2]]
        a.get(3); // 返回 -1（未找到），myHashMap 现在为 [[1,1], [2,2]]
        a.put(2, 1); // myHashMap 现在为 [[1,1], [2,1]]（更新已有的值）
        a.get(2); // 返回 1 ，myHashMap 现在为 [[1,1], [2,1]]
        a.remove(2); // 删除键为 2 的数据，myHashMap 现在为 [[1,1]]
        console.log(a.get(2)); // 返回 -1（未找到），myHashMap 现在为 [[1,1]]
        console.log('a :>> ', a);
    </script>
</body>

</html>